package com.yingxin.yxerp.module.activiti.biz.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yingxin.yx.framework.commons.activiti.dto.*;
import com.yingxin.yx.framework.commons.constant.CommonConst;
import com.yingxin.yx.framework.commons.dto.PageOut;
import com.yingxin.yx.framework.commons.enums.PcOrAppEnums;
import com.yingxin.yx.framework.commons.exception.BizException;
import com.yingxin.yx.framework.commons.id.IdHelper;
import com.yingxin.yx.framework.mybatisplus.PageHelper;
import com.yingxin.yx.framework.user.core.IUserSupport;
import com.yingxin.yxerp.module.activiti.biz.manager.AuditService;
import com.yingxin.yxerp.module.activiti.entity.ActivitiReplaceInfo;
import com.yingxin.yxerp.module.activiti.service.ActivitiProcessService;
import com.yingxin.yxerp.module.activiti.service.ActivitiUserQueryService;
import com.yingxin.yxerp.module.activiti.service.IActHiTaskInstService;
import com.yingxin.yxerp.module.activiti.service.IActivitiReplaceInfoService;
import com.yingxin.yxerp.module.activiti.vo.req.ActivitiReplaceInfoQueryVo;
import com.yingxin.yxerp.module.activiti.vo.resp.ActivitiReplaceInfoRespVo;
import com.yingxin.yxerp.module.common.BusinessTypeHelper;
import com.yingxin.yxerp.module.inform.service.IUserNoticeService;
import com.yingxin.yxerp.module.inform.vo.resp.QtyAndTimeRespVo;
import com.yingxin.yxerp.module.message.constant.UserMsgType;
import com.yingxin.yxerp.module.message.entity.UserMessage;
import com.yingxin.yxerp.module.message.mapper.UserMessageMapper;
import com.yingxin.yxerp.module.message.service.IUserMessageService;
import com.yingxin.yxerp.module.message.vo.req.UserMessageQueryVo;
import com.yingxin.yxerp.module.message.vo.resp.UserMessageRespVo;
import com.yingxin.yxerp.module.organization.entity.User;
import com.yingxin.yxerp.module.organization.service.IUserService;
import com.yingxin.yxerp.module.sys.service.IActivitiCoreInformationService;
import io.swagger.annotations.ApiOperation;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;

/**
 * 表单 前端控制器
 * @author fanchao
 * @since 2021-10-18
 */

@RestController
public class AuditController {

    @Autowired
    private AuditService auditService;

    @Autowired
    private ActivitiUserQueryService activitiUserQueryService;

    @Autowired
    private IUserSupport userSupport;

    @Autowired
    private TaskService taskService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserMessageService userMessageService;

    @Autowired
    @SuppressWarnings("all")
    private UserMessageMapper userMessageMapper;

    @Autowired
    private ActivitiProcessService activitiProcessService;

    @Autowired
    private IActHiTaskInstService actHiTaskInstService;

    @Autowired
    private IActivitiReplaceInfoService activitiReplaceInfoService;

    @Autowired
    private IUserNoticeService userNoticeService;

    @Autowired
    private IActivitiCoreInformationService activitiCoreInformationService;

    @ApiOperation(value = "用户任务数量统计")
    @PostMapping("/activiti/user/taskQtyStat")
    public UserTaskStatInfo listPendingTaskByAssigneeNum(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        User user = userService.getById(userSupport.getUserId());
        if (user == null ) {
            return new UserTaskStatInfo();
        }
        List<UserTaskDto> pendingList = activitiUserQueryService.listPendingTask(user, null);
        Integer unreadQty = userMessageService.countUnreadByReceiverId(user.getId());
        UserMessage userMessage = userMessageService.getCount(user.getId());
        Integer count = activitiReplaceInfoService.getCount(user.getId());
        QtyAndTimeRespVo notice = userNoticeService.getCount(user.getId());
        UserTaskStatInfo stat = new UserTaskStatInfo();
        // 待审核
        stat.setPendingTaskQty(pendingList.size());
        if (pendingList.size() > 0){
            stat.setPendingTaskTime(pendingList.get(0).getCreateTime());
        }
        // 未读信息
        Integer unQty = 0;
        if( unreadQty != null ){
            unQty = unQty + unreadQty;
        }
        if( ObjectUtil.isNotEmpty( notice ) ){
            if( notice.getQty() != null ){
                unQty = unQty + unreadQty;
            }
        }
        stat.setUnreadQty( unQty );
        // 工作通知
        stat.setWorkQty(unreadQty);
        if (userMessage != null){
            stat.setWorkTime(userMessage.getCreateTime());
        }
        // 公告通知
        if( ObjectUtil.isNotEmpty( notice ) ){
            if( notice.getQty() != null ){
                stat.setNoticeQty( notice.getQty() );
            }else{
                stat.setNoticeQty( 0 );
            }
            if (notice.getCreateTime() != null){
                stat.setNoticeTime( notice.getCreateTime() );
            }
        }else {
            stat.setNoticeQty( 0 );
            stat.setNoticeTime( null );
        }
        // 警示通知
        stat.setTotalPendingQty((pendingList.size() + count));
        //待确认
        stat.setReplaceQty(count);
        return stat;
    }

    @ApiOperation(value = "仅查看")
    @PostMapping("/activiti/process/view")
    public ActivitiInstanceDto getProcessInstance(@Valid @NotBlank String id) {
        Task task = taskService.createTaskQuery().taskId(id).singleResult();
        ActivitiInstanceDto dto = activitiUserQueryService.getProcessInstance(task.getProcessInstanceId());
        dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
        return dto;
    }

    /////////////   我的申请
    @ApiOperation(value = "用户查看提交的申请")
    @PostMapping("/activiti/user/process")
    public ActivitiInstanceDto getStartProc(@Valid @NotBlank String id) {
        String userId = userSupport.getUserId();
        ActivitiInstanceDto dto = activitiUserQueryService.getStartProc(userId, id);
        dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
        return dto;
    }

    @ApiOperation(value = "用户查看提交的申请列表")
    @PostMapping("/activiti/user/process/list")
    public PageOut<ActivitiInstanceDto> pageUserProcess(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pageUserProcess(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
            dto.setTaskApprovalStatus(dto.getProcessApprovalStatus());
        }
        return pageOut;
    }

    @ApiOperation(value = "app端 - 用户查看提交的申请列表")
    @PostMapping("/activiti/user/process/app/list")
    public PageOut<ActivitiInstanceDto> pageAppUserProcess(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pageUserProcess(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
            dto.setTaskApprovalStatus(dto.getProcessApprovalStatus());
            dto.setActivitCoreInformationRespVos( activitiCoreInformationService.listByBillId( dto.getBillId() ) );
        }
        return pageOut;
    }




    /////////////   待审核
    @ApiOperation(value = "用户查看待处理任务")
    @PostMapping("/activiti/user/pending-task")
    public ActivitiInstanceDto getPendingTaskByAssignee(@Valid @NotBlank String id) {
        String userId = userSupport.getUserId();
        ActivitiInstanceDto dto = activitiUserQueryService.getPendingTaskByAssignee(userId, id,
                null, null);
        dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
        return dto;
    }

    @ApiOperation(value = "用户查看待处理任务列表")
    @PostMapping("/activiti/user/pending-task/list")
    public PageOut<ActivitiInstanceDto> pagePendingTask(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pagePendingTask(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
        }
        return pageOut;
    }

    @ApiOperation(value = "app端 - 用户查看待处理任务列表")
    @PostMapping("/activiti/user/pending-task/app/list")
    public PageOut<ActivitiInstanceDto> pageAppPendingTask(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pagePendingTask(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName( BusinessTypeHelper.getName(dto.getBillType() ) );
            dto.setId(IdHelper.snowflakeId());
            dto.setActivitCoreInformationRespVos( activitiCoreInformationService.listByBillId( dto.getBillId() ) );
        }
        return pageOut;
    }

    @ApiOperation(value = "查看所有待处理任务列表")
    @PostMapping("/activiti/all/task/list")
    public PageOut<ActivitiInstanceDto> pageAllTask(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto){
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pageAllTask( queryDto );
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
        }
        return pageOut;
    }




    /////////////   已审核
    @ApiOperation(value = "用户查看已处理任务")
    @PostMapping("/activiti/user/completed-task")
    public ActivitiInstanceDto getCompletedTask(@Valid @NotBlank String id) {
        String userId = userSupport.getUserId();
        ActivitiInstanceDto dto = activitiUserQueryService.getCompletedTask(userId, id);
        dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
        return dto;
    }

    @ApiOperation(value = "用户查看已处理任务列表")
    @PostMapping("/activiti/user/completed-task/list")
    public PageOut<ActivitiInstanceDto> pageCompletedTask(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pageCompletedTask(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
        }
        return pageOut;
    }

    @ApiOperation(value = "用户查看已处理任务列表")
    @PostMapping("/activiti/user/completed-task/app/list")
    public PageOut<ActivitiInstanceDto> pageAppCompletedTask(@RequestBody(required = false) ActivitiInstanceQueryDto queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiInstanceQueryDto();
        }
        queryDto.setBizNo(queryDto.getBizNo() == null ? queryDto.getBillNo() : queryDto.getBizNo());
        queryDto.setBizType(queryDto.getBizType() == null ? queryDto.getBillType() : queryDto.getBizType());
        queryDto.setBizTypeName(queryDto.getBizTypeName() == null ? queryDto.getBillTypeName() : queryDto.getBizTypeName());
        String userId = userSupport.getUserId();
        PageOut<ActivitiInstanceDto> pageOut = activitiUserQueryService.pageCompletedTask(userId, queryDto);
        for (ActivitiInstanceDto dto : pageOut.getRows()) {
            dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));
            dto.setId(IdHelper.snowflakeId());
            dto.setActivitCoreInformationRespVos( activitiCoreInformationService.listByBillId( dto.getBillId() ) );
        }
        return pageOut;
    }

    @ApiOperation(value = "用户查看已处理任务")
    @PostMapping("/activiti/user/replace/get/{id}")
    public ActivitiInstanceDto getReplaceById(@PathVariable("id") String id) {
        ActivitiReplaceInfo bill = activitiReplaceInfoService.getById(id);
        ActivitiInstanceDto dto = new ActivitiInstanceDto();
        dto.setBillId(bill.getBizId());
        dto.setBillType(bill.getBizType());
        dto.setBillNo(bill.getBizNo());
        dto.setBillTypeName(BusinessTypeHelper.getName(bill.getBizType()));
        dto.setIsReplace(CommonConst.TRUE);
        return dto;
    }




    /////////////   待确认
    @ApiOperation(value = "用户查看代办代审核列表")
    @PostMapping("/activiti/user/replace/list")
    public PageOut<ActivitiReplaceInfoRespVo> pageReplace(@RequestBody(required = false) ActivitiReplaceInfoQueryVo queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiReplaceInfoQueryVo();
        }
        String userId = userSupport.getUserId();
        queryDto.setConfirmId(userId);
        IPage<ActivitiReplaceInfoRespVo> page = activitiReplaceInfoService.pageVo(PageHelper.in(queryDto), queryDto);
        return PageHelper.out(page);
    }

    @ApiOperation(value = "用户查看代办代审核列表")
    @PostMapping("/activiti/user/replace/app/list")
    public PageOut<ActivitiReplaceInfoRespVo> pageAppReplace(@RequestBody(required = false) ActivitiReplaceInfoQueryVo queryDto) {
        if (queryDto == null) {
            queryDto = new ActivitiReplaceInfoQueryVo();
        }
        String userId = userSupport.getUserId();
        queryDto.setConfirmId(userId);
        IPage<ActivitiReplaceInfoRespVo> page = activitiReplaceInfoService.pageVo(PageHelper.in(queryDto), queryDto);
        for (ActivitiReplaceInfoRespVo dto : page.getRecords()) {
            dto.setActivitCoreInformationRespVos( activitiCoreInformationService.listByBillId( dto.getBusinessId() ) );
        }
        return PageHelper.out(page);
    }

    @ApiOperation(value = "修改确认状态")
    @PostMapping("/activiti/user/replace/update/{id}")
    public void updateReplace(@PathVariable("id") String id) {
        String userId = userSupport.getUserId();
        QueryWrapper<ActivitiReplaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ActivitiReplaceInfo::getBizId,id);
        queryWrapper.lambda().eq(ActivitiReplaceInfo::getConfirmId,userId);
        ActivitiReplaceInfo info = activitiReplaceInfoService.getOne(queryWrapper);
        if (info == null){
            throw new BizException("没有该任务");
        }
        if (CommonConst.TRUE.equals(info.getApprovalStatus())){
            info.setApprovalStatus(CommonConst.FALSE);
        }else {
            info.setApprovalStatus(CommonConst.TRUE);
        }
        activitiReplaceInfoService.updateById(info);

    }




    @ApiOperation(value = "用户查看抄送")
    @PostMapping("/activiti/user/cc")
    public ActivitiInstanceDto getCc(@Valid @NotBlank String id) {
        ActivitiInstanceDto dto = activitiUserQueryService.getProcessInstance(id);
        dto.setBillTypeName(BusinessTypeHelper.getName(dto.getBillType()));

        UpdateWrapper<UserMessage> uw = new UpdateWrapper<>();
        // 审批抄送
        uw.lambda().set(UserMessage::getReadFlag, CommonConst.TRUE);
        uw.lambda().eq(UserMessage::getProcessInstanceId, id);
        uw.lambda().eq(UserMessage::getMessageType, UserMsgType.SP_CC.getType());
        uw.lambda().eq(UserMessage::getReceiverId, userSupport.getUserId());
        userMessageService.update(uw);
        return dto;
    }

    @ApiOperation(value = "用户查看抄送列表")
    @PostMapping("/activiti/user/cc/list")
    public PageOut<UserMessageRespVo> listCcByUser(@RequestBody(required = false) UserMessageQueryVo queryVo) {
        if (queryVo == null) {
            queryVo = new UserMessageQueryVo();
        }
        queryVo.setReceiverId(userSupport.getUserId());
        queryVo.setMessageType(UserMsgType.SP_CC.getType());
        IPage<UserMessageRespVo> page = userMessageMapper.pageVo(PageHelper.in(queryVo), queryVo);
        for (UserMessageRespVo vo : page.getRecords()) {
            vo.setId(IdHelper.snowflakeId());
        }
        return PageHelper.out(page);
    }

    /**
     * 删除指派人重新指派
     * @param auditDto
     */
    @ApiOperation(value = "转办")
    @PostMapping("/activiti/user/task/transfer")
    @Transactional
    public void Transfer(@RequestBody @Valid AuditDto auditDto){
        String userId = userSupport.getUserId();
        Task task = activitiProcessService.getTaskByAssigneeAndId( auditDto.getTaskId(), userId );
        if (task == null) {
            throw new BizException("无法查看该任务");
        }
        /*
        Boolean aBoolean = transferTask(auditDto.getTaskId(), auditDto.getUserId(), auditDto.getVariables());
        if (aBoolean){
            actHiTaskInstService.addActHiTaskInst(auditDto);
        }
        */
        /*taskService.deleteCandidateUser(auditDto.getTaskId(),userId);
        taskService.addCandidateUser(auditDto.getTaskId(),auditDto.getUserId());*/
        taskService.setAssignee( auditDto.getTaskId(), auditDto.getUserId() );
        // 如果要查询转给他人处理的任务，可以同时将OWNER进行设置：
        taskService.setOwner( auditDto.getTaskId(), auditDto.getUserId() );
        actHiTaskInstService.addActHiTaskInst(auditDto);
    }

    /**
     * 强制转办
     * @param auditDto
     */
    @ApiOperation(value = "转办")
    @PostMapping("/activiti/user/task/force-transfer")
    @Transactional
    public void Transfer2(@RequestBody @Valid AuditDto auditDto){
        taskService.setAssignee( auditDto.getTaskId(), auditDto.getUserId() );
        // 如果要查询转给他人处理的任务，可以同时将OWNER进行设置：
        taskService.setOwner( auditDto.getTaskId(), auditDto.getUserId() );
        taskService.addComment(auditDto.getTaskId(), auditDto.getProcessInstanceId(), auditDto.getComment());
        actHiTaskInstService.addActHiTaskInst2(auditDto);
    }

    /**
     * PC端审核通过
     * @param auditDto
     */
    @ApiOperation(value = "审核通过")
    @PostMapping("/activiti/user/task/approved")
    public void approved(@RequestBody @Valid AuditDto auditDto) {
        auditDto.setPcOrApp( PcOrAppEnums.PC.getType() );
        auditService.approved(auditDto);
    }

    /**
     * PC端审核不通过
     * @param auditDto
     */
    @ApiOperation(value = "审核不通过")
    @PostMapping("/activiti/user/task/unapproved")
    public void unapproved(@RequestBody @Valid AuditDto auditDto) {
        auditDto.setPcOrApp( PcOrAppEnums.PC.getType() );
        auditService.unapproved(auditDto);
    }

    /**
     * PC admin强制拒绝
     * @param auditDto
     */
    @ApiOperation(value = "admin强制拒绝")
    @PostMapping("/activiti/user/task/force-approved")
    public void forceApproved(@RequestBody @Valid AuditDto auditDto) {
        auditDto.setPcOrApp( PcOrAppEnums.PC.getType() );
        auditService.forceApproved(auditDto);
    }


    @ApiOperation(value = "撤销用户提交的申请")
    @PostMapping("/activiti/user/process/auditCancel")
    public void auditCancel(@RequestBody @Valid AuditDto auditDto) {
        auditService.auditCancel(auditDto);
    }

    // 审核APP接口
    @ApiOperation(value = "审核通过")
    @PostMapping("/activiti/user/task/mobile/approved")
    public void mobileApproved(@RequestBody @Valid AuditDto auditDto) {
        auditDto.setPcOrApp( PcOrAppEnums.APP.getType() );
        auditService.approved(auditDto);
    }

    @ApiOperation(value = "审核不通过")
    @PostMapping("/activiti/user/task/mobile/unapproved")
    public void unMobileApproved(@RequestBody @Valid AuditDto auditDto) {
        auditDto.setPcOrApp( PcOrAppEnums.APP.getType() );
        auditService.unapproved(auditDto);
    }

}